package com.meraklisina.latexeditor.mdi.Common;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.meraklisina.latexeditor.LatexButton;

public class CommonGuiListener {

	public final static HashMap<String, HashMap<Class, String>> commandClassMethod = new HashMap<String, HashMap<Class, String>>();

	private static List<Class<?>> findClasses(File directory, String packageName) throws ClassNotFoundException {
		List<Class<?>> classes = new ArrayList<Class<?>>();
		if (!directory.exists()) {
			return classes;
		}
		File[] files = directory.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				assert !file.getName().contains(".");
				classes.addAll(findClasses(file, packageName + "." + file.getName()));
			} else if (file.getName().endsWith(".class")) {
				classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
			}
		}
		return classes;
	}

	public static Class<?>[] getClasses(String packageName) throws Exception {
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		assert classLoader != null;
		String path = packageName.replace('.', '/');
		Enumeration<URL> resources = classLoader.getResources(path);
		List<File> dirs = new ArrayList<File>();
		while (resources.hasMoreElements()) {
			URL resource = resources.nextElement();
			dirs.add(new File(resource.toURI()));
		}
		ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
		for (File directory : dirs) {
			classes.addAll(findClasses(directory, packageName));
		}
		return classes.toArray(new Class[classes.size()]);
	}

	public static void handleAction(LatexButton button) throws Exception {

		String command = button.getFullActionTemplate();

		HashMap<Class, String> classMethod = commandClassMethod.get(command);
		if (classMethod == null) {
			System.out.println("Not handled by Common Listener");
			return;
		}
		Iterator<Class> it = classMethod.keySet().iterator();
		while (it.hasNext()) {
			Class<?> cls = it.next();
			String methodName = classMethod.get(cls);
			Method method = cls.getMethod(methodName, null);
			method.invoke(cls, null);
		}

	}

	public static void addhHandlerMethod(Class<?> c, String methodName, String command) {
		HashMap<Class, String> classMethod = commandClassMethod.get(command);
		if (classMethod == null) {
			classMethod = new HashMap<Class, String>();
			commandClassMethod.put(command, classMethod);
		}
		classMethod.put(c, methodName);
	}

	public static void initListeners() throws Exception {
		Class<?>[] classList = getClasses("com.meraklisina.latexeditor.mdi.Common");

		for (Class<?> cls : classList) {
			Class<?> clsInstance = Class.forName(cls.getCanonicalName(), true, Thread.currentThread().getContextClassLoader());

			Method[] methods = cls.getMethods();
			for (Method m : methods) {
				if (m.isAnnotationPresent(LatexCommandHandler.class)) {
					LatexCommandHandler command = m.getAnnotation(LatexCommandHandler.class);
					addhHandlerMethod(clsInstance, m.getName(), command.name());
				}

			}

		}
	}
}
